串接 API 入門:用 fetch 把後端資料顯示在畫面上
這是「接下來可以學什麼」系列的第四篇。學會這篇之後,你的 App 就能不再只是顯示假資料,而是能真正抓取網路上的資料來顯示。
一、為什麼需要學「串接 API」?
到目前為止,前面幾篇範例的資料都是直接寫在程式碼裡的「假資料」(例如固定的貼文列表)。但真實世界的 App,資料通常存在後端伺服器上,App 需要透過網路去「要資料」,這個過程就叫做串接 API。
簡單比喻:API 就像是「點餐窗口」。
- App(你)走到窗口,說「我要某某資料」(發送請求)。
- 後端伺服器(廚房)準備好資料,透過窗口交給你(回傳資料)。
- 你拿到資料後,把它顯示在畫面上。
二、fetch:最基本的發送請求工具
React Native 內建了 fetch 函式,不用額外安裝套件就能直接使用,這是最基礎、最常見的串接 API 方式。
最簡單的範例
fetch('https://example.com/api/posts')
.then((response) => response.json())
.then((data) => {
console.log(data);
});
拆解一下這段在做什麼:
fetch('網址'):發送一個請求到這個網址。.then((response) => response.json()):拿到回應後,把它轉換成 JavaScript 可以讀懂的格式(JSON)。.then((data) => { ... }):拿到轉換後的資料,可以開始使用它。
用 async / await 寫法(比較好讀,現在更常用)
async function getPosts() {
const response = await fetch('https://example.com/api/posts');
const data = await response.json();
console.log(data);
}
這兩種寫法(.then() 跟 async/await)做的事情一樣,只是寫法不同。新手建議直接習慣用 async/await,因為程式碼讀起來會比較像「一步一步往下做」,比較直覺。
三、把 API 資料跟畫面接起來:複習 useState + useEffect
光是抓到資料還不夠,還要把資料存到 State,這樣資料一變化,畫面才會自動更新。這時候就會用到第一篇學過的 useState 跟 useEffect。
import { useState, useEffect } from 'react';
import { View, Text, FlatList } from 'react-native';
export default function PostList() {
const [posts, setPosts] = useState([]); // 用來存放抓到的資料
useEffect(() => {
async function getPosts() {
const response = await fetch('https://example.com/api/posts');
const data = await response.json();
setPosts(data); // 抓到資料後,存進 State
}
getPosts();
}, []); // 空陣列代表:畫面第一次出現時,執行一次就好
return (
<FlatList
data={posts}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => (
<View style={{ padding: 16 }}>
<Text>{item.title}</Text>
</View>
)}
/>
);
}
這段程式碼發生的事情:
- 畫面第一次出現 →
useEffect執行 → 呼叫getPosts()去抓資料。 - 抓到資料後,用
setPosts(data)存進 State。 - State 一改變,畫面自動重新渲染,
FlatList就會把抓到的資料顯示出來。
四、補上「載入中」和「錯誤處理」,做出更完整的體驗
實際開發時,網路請求不會總是立刻成功,可能需要等個一兩秒,也可能會失敗(網路不通、伺服器掛掉、網址打錯)。一個完整的畫面,至少要處理三種狀態:
- 載入中(Loading):資料還在抓,先顯示「載入中…」。
- 成功(Success):資料抓到了,顯示正常內容。
- 失敗(Error):抓資料失敗,顯示錯誤訊息,而不是讓畫面空白或當掉。
import { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
export default function PostList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function getPosts() {
try {
const response = await fetch('https://example.com/api/posts');
if (!response.ok) {
throw new Error('伺服器回應錯誤');
}
const data = await response.json();
setPosts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
getPosts();
}, []);
if (loading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" />
<Text>載入中...</Text>
</View>
);
}
if (error) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>發生錯誤:{error}</Text>
</View>
);
}
return (
<FlatList
data={posts}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => (
<View style={{ padding: 16 }}>
<Text>{item.title}</Text>
</View>
)}
/>
);
}
拆解新增的部分
loading這個 State:一開始是true(代表正在載入),不管成功或失敗,最後都會在finally裡設成false。error這個 State:預設是null(沒有錯誤),如果請求過程出錯,就把錯誤訊息存進去。try / catch / finally:這是 JavaScript 處理「可能會出錯的程式碼」的標準寫法。try裡面放正常流程。catch抓住任何錯誤,存進error。finally不管成功或失敗都會執行,這裡用來把loading關掉。
response.ok:用來檢查伺服器是不是真的回應成功(例如沒有回傳 404、500 這種錯誤狀態碼)。
五、發送資料給伺服器:不只是「拿資料」,也能「送資料」
除了抓資料(通常是 GET 請求),有時候你需要把資料送到伺服器,例如使用者填寫表單、發一篇新貼文。這時候要用 POST 請求,並且要告訴伺服器你送的資料格式:
async function createPost(title) {
const response = await fetch('https://example.com/api/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ title }),
});
const data = await response.json();
return data;
}
拆解一下:
method: 'POST':告訴伺服器,這是要「新增資料」的請求(預設不寫的話,fetch是GET,也就是單純拿資料)。headers:告訴伺服器「我送的資料格式是 JSON」。body:實際要送出去的資料,要用JSON.stringify()轉成字串格式才能送出。
六、新手常見錯誤整理
- ❌ 忘記用
await等待fetch完成,直接拿response當作最終資料使用 → 結果拿到的不是你想要的內容。 - ❌ 沒有處理失敗的情況,網路一斷就整個畫面空白或當掉 → 一定要加上
try / catch或.catch()。 - ❌
useEffect裡忘記寫依賴陣列[]→ 變成每次畫面重新渲染就重新抓一次資料,造成不必要的重複請求,甚至無限迴圈。 - ❌
POST請求忘記設定headers的Content-Type→ 伺服器可能讀不懂你送過去的資料格式。 - ❌ 把網址、API 金鑰直接寫死在程式碼裡到處複製貼上 → 建議統一放在一個設定檔或環境變數管理,之後要換網址或金鑰會比較好維護。
七、小結
fetch是 React Native 內建的請求工具,搭配async/await寫法最直覺。- 抓到的資料要存進
useState,State 改變畫面才會自動更新,這跟第一篇學的概念是一致的。 - 一個完整的畫面至少要處理「載入中」「成功」「失敗」三種狀態,使用者體驗才會完整。
- 不只能「拿資料(GET)」,也能「送資料(POST)」,差別在於
method、headers、body的設定。
把這篇範例改成串接一個你自己找到的公開測試 API(網路上有很多免費的測試用 API),實際抓抓看資料、故意把網址打錯體驗一下「失敗畫面」會怎麼顯示,會比單純看文字更有感覺。下一篇,也是這個系列的最後一篇,我們會接著介紹打包上架:認識 EAS Build / EAS Submit,怎麼把 App 送上 App Store 跟 Google Play。